// SnbThumbnail.cpp : Implementation of CSnbThumbnail

#include "stdafx.h"
#include "snbthumbnail.h"
#include "dllmain.h"

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

#include "utils\skin\myimage.h"
#include "bookreader.h"

// IPersist
STDMETHODIMP CSnbThumbnail::GetClassID(CLSID* pClassID)
{
	*pClassID = CLSID_SnbThumbnail;
	return S_OK;
}

// IPersistFile
STDMETHODIMP CSnbThumbnail::IsDirty()
{
	return E_NOTIMPL;
}

STDMETHODIMP CSnbThumbnail::Load(LPCOLESTR pszFileName, DWORD dwMode)
{
	USES_CONVERSION_EX;
	m_strFileName = OLE2T_EX((LPOLESTR)pszFileName, 0);

	return S_OK;
}

STDMETHODIMP CSnbThumbnail::Save(LPCOLESTR pszFileName, BOOL fRemember)
{
	return E_NOTIMPL;
}

STDMETHODIMP CSnbThumbnail::SaveCompleted(LPCOLESTR pszFileName)
{
	return E_NOTIMPL;
}

STDMETHODIMP CSnbThumbnail::GetCurFile(LPOLESTR* ppszFileName)
{
	return E_NOTIMPL;
}

// IExtractImage
STDMETHODIMP CSnbThumbnail::GetLocation(LPWSTR pszPathBuffer, DWORD cch, DWORD* pdwPriority, const SIZE* prgSize, DWORD dwRecClrDepth, DWORD* pdwFlags)
{
	if (prgSize == NULL || pdwFlags == NULL)
		return E_INVALIDARG;

	m_szThumbnail = *prgSize;

	if (*pdwFlags & IEIFLAG_ASYNC)
		return E_PENDING; 

	return S_OK;
}

STDMETHODIMP CSnbThumbnail::Extract(HBITMAP *phBmpThumbnail)
{
	*phBmpThumbnail = CreateThumbnail(m_szThumbnail);
	return S_OK;
}

// IExtractImage2
STDMETHODIMP CSnbThumbnail::GetDateStamp(FILETIME *pDateStamp)
{
	FILETIME ftCreationTime;
	FILETIME ftLastAccessTime;
	FILETIME ftLastWriteTime;

	HANDLE hFile = CreateFile(m_strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return E_FAIL;

	GetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
	*pDateStamp = ftLastWriteTime;

	CloseHandle(hFile);
	
	return S_OK;
}

HBITMAP CSnbThumbnail::CreateThumbnail(const CSize& szThumbnail)
{
	HBITMAP hThumb = NULL;

	USES_CONVERSION_EX;

	int nSize = 0;
	boost::shared_array<char> pImageData;

	CBookReader BookReader;

	if (BookReader.Load(T2A_EX(m_strFileName, 0)) && 
		BookReader.GetImage("snbc/images/cover.jpg", pImageData, nSize))
	{
		CMyGdiplus initGdiplus;

		CMyImage image;
		image.LoadFromData(pImageData.get(), nSize);

		hThumb = image.Dettach();
	}
	else
	{
		hThumb = LoadBitmap(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDB_THUMBNAIL));
	}

	HDC hDC = CreateCompatibleDC(NULL);
	HBITMAP hBitmap = CreateBitmap(szThumbnail.cx, szThumbnail.cy, GetDeviceCaps(hDC, PLANES), GetDeviceCaps(hDC, BITSPIXEL), NULL); 
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hDC, hBitmap);
	
	CRect rc(0, 0, szThumbnail.cx, szThumbnail.cy);
	FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));

 	HDC hTempDC = CreateCompatibleDC(NULL);
 	SelectObject(hTempDC, hThumb);

	BITMAP bmp;
	GetObject(hThumb, sizeof(BITMAP), &bmp);
	
	int x, y, h, w;
	float xratio = ((float)bmp.bmWidth) / szThumbnail.cx;
	float yratio = ((float)bmp.bmHeight) / szThumbnail.cy;
	if (xratio > yratio)
	{
		x = 0;
		y = (int)((szThumbnail.cy - bmp.bmHeight / xratio) / 2);
		w = szThumbnail.cx;
		h = szThumbnail.cy - 2 * y;
	}
	else
	{
		x = (int)((szThumbnail.cx - bmp.bmWidth / yratio) / 2);
		y = 0;
		w = szThumbnail.cx - 2 * x;
		h = szThumbnail.cy;
	}

	StretchBlt(hDC, x, y, w, h, hTempDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

	DeleteObject(hThumb);
	DeleteDC(hTempDC);

	SelectObject(hDC, hOldBitmap);
	DeleteDC(hDC);

	return hBitmap;
}